<?php

abstract class Module {

	public $name = '';
	public $title = "";
	public static $mainTitle = "";

	/**
	 *
	 * @param string $module
	 * @return Module
	 */
	public static final function getModule($module = 1, $obj = false) {
		if ($module === 1) $module = 'pages';

		$module = "Modules_" . ucwords($module);
		return $obj ? new $module() : $module;
	}

	public /* abstract */ static function subMenu() {
		
	}

	/**
	 *
	 * @return array
	 */
	public abstract function actions();

	/**
	 * @return array
	 */
	public abstract function mainActions();

	/**
	 * @param Blocks $block
	 * @return string
	 */
	public function actionproperties(Blocks $block) {
		if (!$block->action) {
			if ($block->field == 0) {
				$actions = array_keys($this->mainActions());
			} else {
				$actions = array_keys($this->actions());
			}

			$block->action = array_shift($actions);
		}

		return $this->_actionproperties($block);
	}

	/**
	 * @param string $action
	 * @return string
	 */
	protected abstract function _actionproperties(Blocks $block);

	/**
	 * @var string
	 */
	protected $action = null;
	/**
	 *
	 * @var bool
	 */
	protected $is_admin = false;
	/**
	 *
	 * @var string
	 */
	public $template_dir;
	/**
	 *
	 * @var string
	 */
	public $base_url = "?";

	/**
	 *
	 * @param string $action
	 * @param bool	$is_admin
	 */
	public function __construct($action = null, $is_admin = false) {

		$this->action = $action;
		$this->is_admin = $is_admin;

		$this->template_dir = $is_admin ? (RP . "tpl/admin/modules/{$this->name}/") : (RP . "tpl/" . App::getInstance()->page->Template->name . "/modules/{$this->name}/");
		$this->base_url = "?module={$this->name}";
	}

	public function render() {
		$action = ucwords($this->action);
		$action = $this->is_admin ? "adminAction$action" : "action$action";
		
		if(!method_exists($this, $action)) throw new Exception ("Undefined action {$this->action}");

		return $this->$action();
	}

	/**
	 *
	 * @var Templater
	 */
	private $_tpl;

	/**
	 * @return Templater
	 */
	protected function tpl() {
		if (!$this->_tpl) {
			$this->_tpl = new Templater($this->template_dir);
			$this->_tpl->assign(array(
				"base_url" => $this->base_url,
				"tpl_url" => $this->is_admin ? '/tpl/admin/' : "tpl/" . App::getInstance()->page->Template->name . "/",
			));
		}

		return $this->_tpl;
	}

	private $_templatesList;

	public function avaliableTemplatesList($action, $block) {
		if (!$this->_templatesList) {
			$path = RP . "tpl/{$block->Page->Template->name}/modules/{$this->name}/{$block->action}*";
			$glob = glob($path);
			$this->_templatesList = array();
			foreach ($glob as $file) {
				$this->_templatesList[] = pathinfo($file, PATHINFO_BASENAME);
			}
		}

		return $this->_templatesList;
	}

	private $_linkedPages;

	public function avaliableLinkedPages($block) {
		if (!$this->_linkedPages) {
			$field = 0;
			$module_id = $block->module_id;
			$this->_linkedPages = Doctrine_Query::create()
					->from('Blocks b')
					->leftJoin('b.Page')
					->where('field = ? AND module_id = ?', array($field, $module_id))
					->execute();
		}

		return $this->_linkedPages;
	}

	private $_module;

	protected function module() {
		if (!$this->_module) {
			$this->_module = ModulesTable::getInstance()->findByName($this->name)->getFirst();
		}

		return $this->_module;
	}

	/**
	 * @param r|c|d|p $type read, create/edit, delete, publish
	 * @return type 
	 */
	protected function access($type = "r") {
		if (!UserAccess::access($this->name, $type)) {
			header('HTTP/1.1 403 Forbidden');
			throw new Error('403 Forbidden');
		}

		return true;
	}

	/**
	 * @param string $tpl Р’РѕР·РІСЂР°С‰Р°РµС‚ РїСѓС‚СЊ Рє С„Р°Р№Р»Сѓ С€Р°Р±Р»РѕРЅСѓ РёР· РґРµСЂСЂРёРєС‚РѕСЂРёРё Рѕ СѓРјРѕР»С‡Р°РЅРёСЋ
	 * @return string 
	 */
	protected function defaultTpl($tpl) {
		$ds = DIRECTORY_SEPARATOR;
		$name = ucwords($this->name);
		return RP . "inc{$ds}Modules{$ds}{$name}{$ds}tpl{$ds}default{$ds}{$tpl}";
	}

	public function getTpl($tpl) {
		if (!$this->is_admin 
				&& !empty($this->block->tpl) 
				&& strpos(pathinfo($this->block->tpl, PATHINFO_FILENAME), pathinfo($tpl, PATHINFO_FILENAME)) === 0 
				&& file_exists($this->template_dir . $this->block->tpl)) {
			return $this->block->tpl;
		}

		if (file_exists($this->template_dir . $tpl)) return $this->template_dir . $tpl;

		$ds = DIRECTORY_SEPARATOR;
		$name = ucwords($this->name);
		$this->tpl()->template_dir = RP . "inc{$ds}Modules{$ds}{$name}{$ds}tpl{$ds}" . ($this->is_admin ? 'admin' : 'default') . "{$ds}";
		return $this->tpl()->template_dir . $tpl;
	}

	public function getAdminTpl($tpl) {
		if (file_exists($this->template_dir . $tpl)) return $this->template_dir . $tpl;

		$ds = DIRECTORY_SEPARATOR;
		$name = ucwords($this->name);
		$this->tpl()->template_dir = RP . "inc{$ds}Modules{$ds}{$name}{$ds}tpl{$ds}admin{$ds}";
		return $tpl;
	}

	protected final function renderTpl($tpl, $tplData) {
		$this->tpl()->assign($tplData);
		return $this->tpl()->fetch($this->getTpl($tpl));
	}

	protected function chekImgDir($filename = false) {
		if (!$filename) {
			$dr = DIRECTORY_SEPARATOR;
			$filename = RP . "files{$dr}{$this->name}{$dr}src";
		}
		if (!file_exists($filename) || !is_dir($filename)) mkdir($filename, 0777, true);
	}
	
	private $_config;
	
	/**
	 *
	 * @return ModuleConfig
	 */
	public function config(){
		if($this->_config === null){
			$className = "Modules_". ucwords($this->name) . "_Config";
			if(!class_exists($className)) throw new Exception("Config class for module \"{$this->name}\" not defined.");
			$this->_config = new $className();
		}
		
		return $this->_config;
	}
	
	public function adminActionPrp(){
		self::$mainTitle = "Настройки";
		$this->tpl()->assign(array(
			'structure' => $this->config()->structure(),
			'data' => $this->config()->get()
		));
		return $this->tpl()->fetch(Admin::getInstance()->tpl()->template_dir . 'prp.html');
	}
	
	public function adminActionPrp_save(){
		$this->access('c');
		$this->access('r');
		$this->access('d');
		$this->access('p');
		
		$data = $_REQUEST['config'];
		$this->config()->set($data)->save();
		
		Request::redirect(-1);
	}

}

